#include "SimpleKey.h"

/**
 * @brief SimpleKey构造函数
 * @param pin 按键引脚编号
 */
SimpleKey::SimpleKey(uint8_t pin) {
  this->pin = pin;
  this->state = KeyState::Idle;
  this->pressTime = 0;
  this->shortPressCallback = nullptr;
  this->longPressCallback = nullptr;
  
  // 设置引脚为输入上拉模式
  pinMode(pin, INPUT_PULLUP);
}

/**
 * @brief 更新按键状态机
 * @details 该函数需要在主循环中周期性调用，用于检测按键状态变化并触发相应回调
 */
void SimpleKey::update() {
  // 读取当前按键状态（低电平表示按下）
  bool keyPressed = (digitalRead(pin) == LOW);
  unsigned long currentTime = millis();
  
  // 按键状态机
  switch (state) {
    case KeyState::Idle:
      if (keyPressed) {
        // 按键按下，记录时间并进入去抖动
        pressTime = currentTime;
        state = KeyState::ShortPress;
      }
      break;
      
    case KeyState::ShortPress:
      if (!keyPressed) {
        // 按键释放
        if ((currentTime - pressTime) >= DEBOUNCE_TIME) {
          // 去抖动时间已过，确认为短按
          if (shortPressCallback != nullptr) {
            shortPressCallback(); // 触发短按回调
          }
        }
        // 无论如何都返回空闲状态
        state = KeyState::Idle;
      } else if ((currentTime - pressTime) >= LONG_PRESS_TIME) {
        // 按键持续按下超过长按时间
        state = KeyState::LongPress;
        if (longPressCallback != nullptr) {
          longPressCallback(); // 触发长按回调
        }
      }
      break;
      
    case KeyState::LongPress:
      if (!keyPressed) {
        // 长按后释放，返回空闲状态
        state = KeyState::Idle;
      }
      break;
  }
}

/**
 * @brief 注册短按事件回调函数
 * @param callback 回调函数指针
 */
void SimpleKey::onShortPress(KeyEventCallback callback) {
  this->shortPressCallback = callback;
}

/**
 * @brief 注册长按事件回调函数
 * @param callback 回调函数指针
 */
void SimpleKey::onLongPress(KeyEventCallback callback) {
  this->longPressCallback = callback;
}

/**
 * @brief 检查按键是否被按下
 * @return true表示按下，false表示未按下
 */
bool SimpleKey::isPressed() const {
  return (digitalRead(pin) == LOW);
}